// Factory
// (c) jimon game studio

#ifndef JEH_JEFACTORY
#define JEH_JEFACTORY

#include "jeList.h"
#include "jeString.h"
#include "jeMap.h"

namespace je
{
	template<class BaseType,class TName = jeStringc>
	class jeFactory
	{
	public:
		//! Base Type Creator
		class BaseTypeCreator
		{
		public:
			virtual ~BaseTypeCreator(){}
			virtual BaseType * Create() = 0;
		};
	protected:
		template<class T>
		class DescribedTypeCreator:public BaseTypeCreator
		{
		public:
			BaseType * Create()
			{
				T * NewCreate = NULL;
				JENEW(NewCreate,T)
				return NewCreate;
			}
		};

		typedef jeMap<TName,BaseTypeCreator*> CreatorsMapType;
		CreatorsMapType CreatorsMap;
	public:
		//! Constructor
		jeFactory()
		{
		}

		//! Destructor
		~jeFactory()
		{
			for(typename CreatorsMapType::Iterator Iter = CreatorsMap.getIterator();!Iter.atEnd();Iter++)
				JEDELETE(Iter->getValue())
			CreatorsMap.clear();
		}

		//! Create
		BaseType * Create(const TName & Name)
		{
			typename CreatorsMapType::Node * Node = CreatorsMap.find(Name);
			if(Node)
				return Node->getValue()->Create();
			else
				return NULL;
		}

		//! Register Creator
		template<class DescribedType>
		void Register(const TName & Name)
		{
			if(CreatorsMap.find(Name))
				return;

			BaseTypeCreator * Creator = NULL;
			JENEW(Creator,DescribedTypeCreator<DescribedType>)
			CreatorsMap[Name] = Creator;
		}

		//! Register Creator
		void RegisterDiscribedClass(const TName & Name,BaseTypeCreator * Creator)
		{
			if(CreatorsMap.find(Name))
				return;

			CreatorsMap[Name] = Creator;
		}
	};
}
#endif
